import React, { useRef, useEffect, useState, useCallback } from 'react'
import { Card, Button, Space, Typography, message } from 'antd'
import { CameraOutlined, AimOutlined, SettingOutlined } from '@ant-design/icons'
import { useWebSocket } from '../../hooks/useWebSocket'
import { Utils } from '../../utils'
import './CameraView.css'

const { Text } = Typography

const CameraView = () => {
  const cameraFeedRef = useRef(null)
  const cameraWrapperRef = useRef(null)
  const roiDivRef = useRef(null)
  const cameraFeedTimerRef = useRef(null)
  
  const { connected, sendKey } = useWebSocket()
  
  // ROI相关状态
  const [roiState, setRoiState] = useState({
    freezeMode: false,
    rectData: null,
    start: null,
    rect: null,
    dragging: false
  })
  
  // 摄像头状态
  const [cameraStatus, setCameraStatus] = useState({
    connected: false,
    loading: true,
    error: null,
    retryCount: 0
  })

  const maxRetries = 3

  // 获取图像显示信息
  const getImageDisplayInfo = useCallback(() => {
    const cameraFeed = cameraFeedRef.current
    const cameraWrapper = cameraWrapperRef.current
    if (!cameraFeed || !cameraWrapper) return null
    
    const rect = cameraFeed.getBoundingClientRect()
    const wrapperRect = cameraWrapper.getBoundingClientRect()
    const imgAspectRatio = cameraFeed.naturalWidth / cameraFeed.naturalHeight
    const wrapperAspectRatio = wrapperRect.width / wrapperRect.height
    
    let displayWidth, displayHeight, offsetX, offsetY
    
    if (imgAspectRatio > wrapperAspectRatio) {
      displayWidth = wrapperRect.width
      displayHeight = wrapperRect.width / imgAspectRatio
      offsetX = 0
      offsetY = (wrapperRect.height - displayHeight) / 2
    } else {
      displayHeight = wrapperRect.height
      displayWidth = wrapperRect.height * imgAspectRatio
      offsetX = (wrapperRect.width - displayWidth) / 2
      offsetY = 0
    }
    
    return {
      displayWidth,
      displayHeight,
      offsetX,
      offsetY,
      scaleX: cameraFeed.naturalWidth / displayWidth,
      scaleY: cameraFeed.naturalHeight / displayHeight
    }
  }, [])

  // 鼠标坐标转图像坐标
  const mouseToImageCoords = useCallback((mouseX, mouseY) => {
    const info = getImageDisplayInfo()
    if (!info) return { x: 0, y: 0 }
    
    const cameraFeed = cameraFeedRef.current
    const imageX = (mouseX - info.offsetX) * info.scaleX
    const imageY = (mouseY - info.offsetY) * info.scaleY
    
    return {
      x: Math.max(0, Math.min(cameraFeed.naturalWidth, imageX)),
      y: Math.max(0, Math.min(cameraFeed.naturalHeight, imageY))
    }
  }, [getImageDisplayInfo])

  // 图像坐标转显示坐标
  const imageToDisplayCoords = useCallback((imageX, imageY) => {
    const info = getImageDisplayInfo()
    if (!info) return { x: 0, y: 0 }
    
    return {
      x: imageX / info.scaleX + info.offsetX,
      y: imageY / info.scaleY + info.offsetY
    }
  }, [getImageDisplayInfo])

  // 获取图像内容区域
  const getImageContentRect = useCallback((img) => {
    const rect = img.getBoundingClientRect()
    if (!img.naturalWidth || !img.naturalHeight || rect.width === 0 || rect.height === 0) {
      return null
    }
    
    const imgAspect = img.naturalWidth / img.naturalHeight
    const rectAspect = rect.width / rect.height
    let contentLeft, contentTop, contentWidth, contentHeight
    
    if (imgAspect > rectAspect) {
      contentWidth = rect.width
      contentHeight = rect.width / imgAspect
      contentLeft = rect.left
      contentTop = rect.top + (rect.height - contentHeight) / 2
    } else {
      contentHeight = rect.height
      contentWidth = rect.height * imgAspect
      contentTop = rect.top
      contentLeft = rect.left + (rect.width - contentWidth) / 2
    }
    
    return { left: contentLeft, top: contentTop, width: contentWidth, height: contentHeight }
  }, [])

  // 启动摄像头画面轮询
  const startCameraFeed = useCallback(() => {
    if (cameraFeedTimerRef.current) {
      clearInterval(cameraFeedTimerRef.current)
    }
    
    const cameraFeed = cameraFeedRef.current
    if (!cameraFeed) return
    
    setCameraStatus(prev => ({ ...prev, loading: true, error: null }))
    
    const loadCameraFeed = () => {
      if (!roiState.freezeMode) {
        const timestamp = Date.now()
        const newSrc = `http://127.0.0.1:5000/video_feed?t=${timestamp}`
        
        cameraFeed.onerror = () => {
          setCameraStatus(prev => {
            const newRetryCount = prev.retryCount + 1
            if (newRetryCount >= maxRetries) {
              clearInterval(cameraFeedTimerRef.current)
              return {
                ...prev,
                connected: false,
                loading: false,
                error: '摄像头连接失败',
                retryCount: newRetryCount
              }
            }
            return { ...prev, retryCount: newRetryCount }
          })
        }
        
        cameraFeed.onload = () => {
          setCameraStatus({
            connected: true,
            loading: false,
            error: null,
            retryCount: 0
          })
        }
        
        cameraFeed.src = newSrc
      }
    }
    
    loadCameraFeed()
    cameraFeedTimerRef.current = setInterval(loadCameraFeed, 200)
  }, [roiState.freezeMode])

  // 鼠标按下事件
  const handleMouseDown = useCallback((e) => {
    if (!roiState.freezeMode || e.button !== 0) return
    
    const imageCoords = mouseToImageCoords(e.nativeEvent.offsetX, e.nativeEvent.offsetY)
    const displayCoords = imageToDisplayCoords(imageCoords.x, imageCoords.y)
    
    setRoiState(prev => ({
      ...prev,
      dragging: true,
      start: imageCoords
    }))
    
    const roiDiv = roiDivRef.current
    if (roiDiv) {
      roiDiv.style.display = 'block'
      roiDiv.style.position = 'absolute'
      roiDiv.style.left = displayCoords.x + 'px'
      roiDiv.style.top = displayCoords.y + 'px'
      roiDiv.style.width = '0px'
      roiDiv.style.height = '0px'
    }
  }, [roiState.freezeMode, mouseToImageCoords, imageToDisplayCoords])

  // 鼠标移动事件
  const handleMouseMove = useCallback((e) => {
    if (!roiState.freezeMode || !roiState.dragging || !roiState.start) return
    
    const currentImageCoords = mouseToImageCoords(e.nativeEvent.offsetX, e.nativeEvent.offsetY)
    const sx = Math.min(roiState.start.x, currentImageCoords.x)
    const sy = Math.min(roiState.start.y, currentImageCoords.y)
    const ex = Math.max(roiState.start.x, currentImageCoords.x)
    const ey = Math.max(roiState.start.y, currentImageCoords.y)
    
    const rect = { sx, sy, ex, ey }
    const startDisplay = imageToDisplayCoords(sx, sy)
    const endDisplay = imageToDisplayCoords(ex, ey)
    
    setRoiState(prev => ({ ...prev, rect }))
    
    const roiDiv = roiDivRef.current
    if (roiDiv) {
      roiDiv.style.display = 'block'
      roiDiv.style.position = 'absolute'
      roiDiv.style.left = startDisplay.x + 'px'
      roiDiv.style.top = startDisplay.y + 'px'
      roiDiv.style.width = (endDisplay.x - startDisplay.x) + 'px'
      roiDiv.style.height = (endDisplay.y - startDisplay.y) + 'px'
    }
  }, [roiState.freezeMode, roiState.dragging, roiState.start, mouseToImageCoords, imageToDisplayCoords])

  // 鼠标松开事件
  const handleMouseUp = useCallback(() => {
    if (!roiState.freezeMode || !roiState.dragging || !roiState.rect) return
    
    const roiWidth = roiState.rect.ex - roiState.rect.sx
    const roiHeight = roiState.rect.ey - roiState.rect.sy
    const minSize = 10
    
    if (roiWidth < minSize || roiHeight < minSize) {
      message.warning('ROI区域太小，请重新选择')
      const roiDiv = roiDivRef.current
      if (roiDiv) roiDiv.style.display = 'none'
      setRoiState(prev => ({
        ...prev,
        dragging: false,
        start: null,
        rect: null
      }))
      return
    }
    
    const cameraFeed = cameraFeedRef.current
    if (roiState.rect.sx < 0 || roiState.rect.sy < 0 ||
        roiState.rect.ex > cameraFeed.naturalWidth || roiState.rect.ey > cameraFeed.naturalHeight) {
      message.warning('ROI区域超出图像范围，请重新选择')
      const roiDiv = roiDivRef.current
      if (roiDiv) roiDiv.style.display = 'none'
      setRoiState(prev => ({
        ...prev,
        dragging: false,
        start: null,
        rect: null
      }))
      return
    }
    
    const rectData = {
      x: Math.round(roiState.rect.sx),
      y: Math.round(roiState.rect.sy),
      w: Math.round(roiWidth),
      h: Math.round(roiHeight)
    }
    
    setRoiState(prev => ({
      ...prev,
      rectData,
      dragging: false,
      start: null,
      rect: null
    }))
    
    message.success('ROI区域已选择，按Enter提交')
  }, [roiState.freezeMode, roiState.dragging, roiState.rect])

  // 点击事件（设定摆心）
  const handleClick = useCallback((e) => {
    if (roiState.freezeMode) return
    
    const cameraFeed = cameraFeedRef.current
    const contentRect = getImageContentRect(cameraFeed)
    if (!contentRect) return
    
    const px = e.clientX - contentRect.left
    const py = e.clientY - contentRect.top
    const scaleX = cameraFeed.naturalWidth / contentRect.width
    const scaleY = cameraFeed.naturalHeight / contentRect.height
    const sendX = Math.round(px * scaleX)
    const sendY = Math.round(py * scaleY)
    
    if (px < 0 || py < 0 || px > contentRect.width || py > contentRect.height) return
    
    fetch('http://127.0.0.1:5000/pendulum_mouse', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ type: 'left', x: sendX, y: sendY })
    })
    
    Utils.showToast('摆心位置已设定', 'success')
  }, [roiState.freezeMode, getImageContentRect])

  // 右键事件（设定坐标轴零点）
  const handleContextMenu = useCallback((e) => {
    if (roiState.freezeMode) return
    e.preventDefault()
    
    const cameraFeed = cameraFeedRef.current
    const contentRect = getImageContentRect(cameraFeed)
    if (!contentRect) return
    
    const px = e.clientX - contentRect.left
    const py = e.clientY - contentRect.top
    const scaleX = cameraFeed.naturalWidth / contentRect.width
    const scaleY = cameraFeed.naturalHeight / contentRect.height
    const sendX = Math.round(px * scaleX)
    const sendY = Math.round(py * scaleY)
    
    if (px < 0 || py < 0 || px > contentRect.width || py > contentRect.height) return
    
    fetch('http://127.0.0.1:5000/pendulum_mouse', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ type: 'right', x: sendX, y: sendY })
    })
    
    Utils.showToast('坐标轴零点已设定', 'success')
  }, [roiState.freezeMode, getImageContentRect])

  // 进入ROI模式
  const enterROIMode = useCallback(() => {
    const cameraFeed = cameraFeedRef.current
    if (!cameraFeed.naturalWidth || !cameraFeed.naturalHeight) {
      message.warning('摄像头未就绪，请稍后再试')
      return
    }
    
    fetch('http://127.0.0.1:5000/pendulum_pause', { method: 'POST' })
    
    setRoiState(prev => ({ ...prev, freezeMode: true }))
    
    if (cameraFeedTimerRef.current) {
      clearInterval(cameraFeedTimerRef.current)
    }
    
    const messageText = `画面已冻结，请用鼠标拖拽选取小球区域进行HSV校准。

选择技巧：
1. 选择包含小球颜色的区域
2. 避免选择背景或其他物体
3. 区域大小建议20x20像素以上
4. 选完后按Enter提交

当前图像尺寸: ${cameraFeed.naturalWidth}x${cameraFeed.naturalHeight}`
    
    message.info(messageText, 5)
    Utils.showToast('进入ROI框选模式', 'info')
  }, [])

  // 提交ROI
  const submitROI = useCallback(() => {
    if (!roiState.rectData) {
      message.warning('请先选择ROI区域')
      return
    }
    
    if (roiState.rectData.w < 10 || roiState.rectData.h < 10) {
      message.warning('ROI区域太小，请重新选择')
      return
    }
    
    fetch('http://127.0.0.1:5000/pendulum_roi', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(roiState.rectData)
    })
    .then(r => r.json())
    .then(data => {
      if (data.success) {
        message.success('HSV校准成功！')
      } else {
        message.error('HSV校准失败：' + (data.error || '未知错误'))
      }
    })
    .catch(() => {
      message.error('ROI提交失败，请重试')
    })
    
    fetch('http://127.0.0.1:5000/pendulum_resume', { method: 'POST' })
    
    setRoiState({
      freezeMode: false,
      rectData: null,
      start: null,
      rect: null,
      dragging: false
    })
    
    startCameraFeed()
    
    const roiDiv = roiDivRef.current
    if (roiDiv) roiDiv.style.display = 'none'
  }, [roiState.rectData, startCameraFeed])

  // 键盘事件处理
  useEffect(() => {
    const handleKeyDown = (e) => {
      // ROI提交
      if (roiState.freezeMode && e.key === 'Enter' && roiState.rectData) {
        submitROI()
        return
      }
      
      // 进入ROI模式
      if (e.key === 'c' && !roiState.freezeMode) {
        enterROIMode()
        return
      }
      
      // 发送快捷键到后端
      if (!roiState.freezeMode && (e.key.length === 1 || ['ArrowUp','ArrowDown','ArrowLeft','ArrowRight'].includes(e.key))) {
        if (connected && sendKey) {
          sendKey(e.key)
          Utils.showToast('已发送快捷键：' + e.key, 'info')
        }
      }
    }
    
    document.addEventListener('keydown', handleKeyDown)
    return () => document.removeEventListener('keydown', handleKeyDown)
  }, [roiState.freezeMode, roiState.rectData, connected, sendKey, submitROI, enterROIMode])

  // 鼠标事件处理
  useEffect(() => {
    const handleGlobalMouseUp = () => {
      handleMouseUp()
    }
    
    window.addEventListener('mouseup', handleGlobalMouseUp)
    return () => window.removeEventListener('mouseup', handleGlobalMouseUp)
  }, [handleMouseUp])

  // 初始化
  useEffect(() => {
    startCameraFeed()
    
    return () => {
      if (cameraFeedTimerRef.current) {
        clearInterval(cameraFeedTimerRef.current)
      }
    }
  }, [startCameraFeed])

  const getStatusText = () => {
    if (cameraStatus.loading) return '🔄 正在连接摄像头...'
    if (cameraStatus.error) return `❌ ${cameraStatus.error}`
    if (cameraStatus.connected) return '✅ 摄像头已连接'
    return '🟡 等待摄像头数据...'
  }

  const getStatusColor = () => {
    if (cameraStatus.loading) return '#ff9800'
    if (cameraStatus.error) return '#f44336'
    if (cameraStatus.connected) return '#4caf50'
    return '#ffc107'
  }

  return (
    <Card 
      title="摄像头画面"
      className="camera-view-card"
      extra={
        <Space>
          <Button 
            icon={<AimOutlined />}
            onClick={enterROIMode}
            disabled={roiState.freezeMode || !cameraStatus.connected}
            size="small"
          >
            HSV校准
          </Button>
          {roiState.freezeMode && (
            <Button 
              type="primary"
              onClick={submitROI}
              disabled={!roiState.rectData}
              size="small"
            >
              提交ROI
            </Button>
          )}
        </Space>
      }
    >
      <div className="camera-container">
        <div 
          ref={cameraWrapperRef}
          className="camera-wrapper"
          onMouseDown={handleMouseDown}
          onMouseMove={handleMouseMove}
          onClick={handleClick}
          onContextMenu={handleContextMenu}
        >
          <img 
            ref={cameraFeedRef}
            className={`camera-feed ${roiState.freezeMode ? 'frozen' : ''}`}
            src="http://127.0.0.1:5000/video_feed"
            alt="摄像头画面"
            draggable={false}
            style={{ opacity: cameraStatus.connected ? 1 : 0.3 }}
          />
          <div 
            ref={roiDivRef}
            className="roi-selection"
            style={{ display: 'none' }}
          />
        </div>
        <div 
          className="sync-status"
          style={{ color: getStatusColor() }}
        >
          {getStatusText()}
        </div>
      </div>
    </Card>
  )
}

export default CameraView
